<?php
// no direct access
defined('_JEXEC') or die('Restricted access');

/**
 * This file is part of the PHP_Word_Cloud project.
 * http://github.com/sixty-nine/PHP_Word_Cloud
 *
 * @author Daniel Barsotti / dan [at] dreamcraft [dot] ch
 * @license http://creativecommons.org/licenses/by-nc-sa/3.0/
 *          Creative Commons Attribution-NonCommercial-ShareAlike 3.0
 */

class WordCloud
{

    private $width, $height;
    private $font;
    private $mask;
    private $table;
    private $image;
    private $imagecolor;

    public function __construct(
        $minFontSize, $maxFontSize,
        $width, $height,
        $font,
        $text = null,
        $imagecolor = array(0, 0, 0, 127),
        $words_limit = null,
        $vertical_freq = FrequencyTable::WORDS_MAINLY_HORIZONTAL)
    {
        $this->width = $width;
        $this->height = $height;
        $this->font = $font;
        $this->imagecolor = $imagecolor;

        $this->mask = new Mask();

        $this->table = new FrequencyTable($minFontSize, $maxFontSize, $font, '', $vertical_freq, $words_limit); //, $text);
        $this->table->setMinFontSize($minFontSize);
        $this->table->setMaxFontSize($maxFontSize);

        if (is_array($text)) {
            foreach ($text as $row) {
                if (!isset($row['title'])) $row['title'] = null;
                $this->table->add_word($row['word'], $row['count'], $row['title'], $row['link']);
            }
        } else {
            $this->table->processText($text);
        }
        $this->table->buildCloud();


        /*
        $this->table = new FrequencyTable($font);//, $text);
        $this->table->add_word('word1');
        $this->table->add_word('word2', 2);
        $this->table->add_word('word3');
        $this->table->add_word('word4', 4);
        $this->table->add_word('word5');*/
        // for($i = 6; $i <= 20; $i++) $this->table->add_word('word'.$i, $i % 5);

        $this->image = imagecreatetruecolor($width, $height);
        //Set the flag to save full alpha channel information (as opposed to single-color transparency) when saving PNG images
        imagesavealpha($this->image, true);
        //behaves identically to imagecolorallocate() with the addition of the transparency parameter alpha
        $trans_colour = imagecolorallocatealpha($this->image, $imagecolor[0], $imagecolor[1], $imagecolor[2], $imagecolor[3]);
        imagefill($this->image, 0, 0, $trans_colour);

    }

    public function get_image()
    {
        return $this->image;
    }

    public function render($palette)
    {
        $i = 0;
        $positions = array();

        foreach ($this->table->get_table() as $key => $val) {
            // Set the center so that vertical words are better distributed
            if ($val->angle == 0) {
                $cx = $this->width / 3;
                $cy = $this->height / 2;
            } else {
                $cx = $this->width / 3 + rand(0, $this->width / 10);
                $cy = $this->height / 2 + rand(-$this->height / 10, $this->height / 10);
            }

            // Search the place for the next word
            list($cx, $cy) = $this->mask->search_place($this->image, $cx, $cy, $val->box);

            // Draw the word
            $res['words'][$key] = array(
                'x' => $cx,
                'y' => $cy,
                'angle' => $val->angle,
                'size' => $val->size,
                'color' => $palette[$i % count($palette)],
                'box' => isset($boxes[$key]) ? $boxes[$key] : '',
            );
            imagettftext($this->image, $val->size, $val->angle, $cx, $cy, $palette[$i % count($palette)], $this->font, $key);
            $this->mask->add(new Box($cx, $cy, $val->box));
            $i++;
        }

        // Crop the image
        list($x1, $y1, $x2, $y2) = $this->mask->get_bounding_box();
        $image2 = imagecreatetruecolor(abs($x2 - $x1), abs($y2 - $y1));

        //Set the flag to save full alpha channel information (as opposed to single-color transparency) when saving PNG images
        imagesavealpha($image2, true);
        //behaves identically to imagecolorallocate() with the addition of the transparency parameter alpha
        $trans_colour = imagecolorallocatealpha($image2, $this->imagecolor[0], $this->imagecolor[1], $this->imagecolor[2], $this->imagecolor[3]);
        imagefill($image2, 0, 0, $trans_colour);

        imagecopy($image2, $this->image, 0, 0, $x1, $y1, abs($x2 - $x1), abs($y2 - $y1));


        imagedestroy($this->image);
        $this->image = $image2;

        // Adjust the map to the cropped image
        $this->mask->adjust(-$x1, -$y1);

        foreach ($boxes = $this->get_image_map() as $map) {
            $res['words'][$map[0]]['box'] = $map[1];
        }

        $res['adjust'] = array('dx' => -$x1, 'dy' => -$y1);
        return $res;
    }

    public function get_image_map()
    {

        $words = $this->table->get_table();
        $boxes = $this->mask->get_table();
        if (count($boxes) != count($words)) {
            throw new Exception('Error: mask count <> word count');
        }

        $map = array();
        $i = 0;
        foreach ($words as $key => $val) {
            $map[] = array($key, $boxes[$i], $val->title, $val->link);
            $i++;
        }

        return $map;
    }
}

